package org.unique.support.template;

import java.io.PrintWriter;
import java.util.Enumeration;
import java.util.Iterator;
import java.util.Map.Entry;
import java.util.Properties;
import java.util.Set;

import javax.servlet.ServletContext;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.velocity.Template;
import org.apache.velocity.VelocityContext;
import org.apache.velocity.app.Velocity;
import org.apache.velocity.exception.ParseErrorException;
import org.apache.velocity.exception.ResourceNotFoundException;
import org.unique.Const;
import org.unique.web.render.Render;
import org.unique.web.render.RenderException;

/**
 * velocity render
 * 
 * @author biezhi
 * @version 1.0
 */
public class VelocityRender implements Render {

	private static final String contentType = "text/html;charset="
			+ Const.ENCODING;
	private static final Properties properties = new Properties();
	private static boolean notInit = true;

	public VelocityRender() {
	}

	static void init(ServletContext servletContext) {
		String webPath = servletContext.getRealPath("/");
		properties.setProperty(Velocity.FILE_RESOURCE_LOADER_PATH, webPath);
		properties.setProperty(Velocity.ENCODING_DEFAULT, Const.ENCODING);
		properties.setProperty(Velocity.INPUT_ENCODING, Const.ENCODING);
		properties.setProperty(Velocity.OUTPUT_ENCODING, Const.ENCODING);
	}

	public static void setProperties(Properties properties) {
		Set<Entry<Object, Object>> set = properties.entrySet();
		for (Iterator<Entry<Object, Object>> it = set.iterator(); it.hasNext();) {
			Entry<Object, Object> e = it.next();
			VelocityRender.properties.put(e.getKey(), e.getValue());
		}
	}

	public void render(HttpServletRequest request, HttpServletResponse response, String viewPath) {
		if (notInit) {
			Velocity.init(properties); 
			notInit = false;
		}
		String view = viewPath + suffix;
		if(viewPath.endsWith(suffix)){
			view = viewPath;
		}
		view = view.replaceAll("//", "/");
		PrintWriter writer = null;
		try {
			VelocityContext context = new VelocityContext();

			// Map root = new HashMap();
			for (Enumeration<String> attrs = request.getAttributeNames(); attrs
					.hasMoreElements();) {
				String attrName = attrs.nextElement();
				context.put(attrName, request.getAttribute(attrName));
			}

			Template template = Velocity.getTemplate(view);

			/*
			 * Now have the template engine process your template using the data
			 * placed into the context. Think of it as a 'merge' of the template
			 * and the data to produce the output stream.
			 */
			response.setContentType(contentType);
			writer = response.getWriter(); 	// BufferedWriter writer = new
											// BufferedWriter(new
											// OutputStreamWriter(System.out));

			template.merge(context, writer);
			writer.flush(); // flush and cleanup
		} catch (ResourceNotFoundException e) {
			throw new RenderException("Example : error : cannot find template " + view, e);
		} catch (ParseErrorException e) {
			throw new RenderException("Example : Syntax error in template "
					+ view + ":" + e, e);
		} catch (Exception e) {
			throw new RenderException(e);
		} finally {
			if (writer != null){
				writer.close();
			}
		}
	}

}
